'\"
'\" Copyright (c) 1994 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: fileevent.n,v 1.2 2003/11/24 05:09:59 bbbush Exp $
'\" 
'\" The definitions below are for supplemental macros used in Tcl/Tk
'\" manual entries.
'\"
'\" .AP type name in/out ?indent?
'\"	Start paragraph describing an argument to a library procedure.
'\"	type is type of argument (int, etc.), in/out is either "in", "out",
'\"	or "in/out" to describe whether procedure reads or modifies arg,
'\"	and indent is equivalent to second arg of .IP (shouldn't ever be
'\"	needed;  use .AS below instead)
'\"
'\" .AS ?type? ?name?
'\"	Give maximum sizes of arguments for setting tab stops.  Type and
'\"	name are examples of largest possible arguments that will be passed
'\"	to .AP later.  If args are omitted, default tab stops are used.
'\"
'\" .BS
'\"	Start box enclosure.  From here until next .BE, everything will be
'\"	enclosed in one large box.
'\"
'\" .BE
'\"	End of box enclosure.
'\"
'\" .CS
'\"	Begin code excerpt.
'\"
'\" .CE
'\"	End code excerpt.
'\"
'\" .VS ?version? ?br?
'\"	Begin vertical sidebar, for use in marking newly-changed parts
'\"	of man pages.  The first argument is ignored and used for recording
'\"	the version when the .VS was added, so that the sidebars can be
'\"	found and removed when they reach a certain age.  If another argument
'\"	is present, then a line break is forced before starting the sidebar.
'\"
'\" .VE
'\"	End of vertical sidebar.
'\"
'\" .DS
'\"	Begin an indented unfilled display.
'\"
'\" .DE
'\"	End of indented unfilled display.
'\"
'\" .SO
'\"	Start of list of standard options for a Tk widget.  The
'\"	options follow on successive lines, in four columns separated
'\"	by tabs.
'\"
'\" .SE
'\"	End of list of standard options for a Tk widget.
'\"
'\" .OP cmdName dbName dbClass
'\"	Start of description of a specific option.  cmdName gives the
'\"	option's name as specified in the class command, dbName gives
'\"	the option's name in the option database, and dbClass gives
'\"	the option's class in the option database.
'\"
'\" .UL arg1 arg2
'\"	Print arg1 underlined, then print arg2 normally.
'\"
'\" RCS: @(#) $Id: fileevent.n,v 1.2 2003/11/24 05:09:59 bbbush Exp $
'\"
'\"	# Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
.if t .wh -1.3i ^B
.nr ^l \n(.l
.ad b
'\"	# Start an argument description
.de AP
.ie !"\\$4"" .TP \\$4
.el \{\
.   ie !"\\$2"" .TP \\n()Cu
.   el          .TP 15
.\}
.ta \\n()Au \\n()Bu
.ie !"\\$3"" \{\
\&\\$1	\\fI\\$2\\fP	(\\$3)
.\".b
.\}
.el \{\
.br
.ie !"\\$2"" \{\
\&\\$1	\\fI\\$2\\fP
.\}
.el \{\
\&\\fI\\$1\\fP
.\}
.\}
..
'\"	# define tabbing values for .AP
.de AS
.nr )A 10n
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
.nr )B \\n()Au+15n
.\"
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
.nr )C \\n()Bu+\\w'(in/out)'u+2n
..
.AS Tcl_Interp Tcl_CreateInterp in/out
'\"	# BS - start boxed text
'\"	# ^y = starting y location
'\"	# ^b = 1
.de BS
.br
.mk ^y
.nr ^b 1u
.if n .nf
.if n .ti 0
.if n \l'\\n(.lu\(ul'
.if n .fi
..
'\"	# BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
.mk ^t
.ie n \l'\\n(^lu\(ul'
.el \{\
.\"	Draw four-sided box normally, but don't draw top of
.\"	box if the box started on an earlier page.
.ie !\\n(^b-1 \{\
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
'\"	# VS - start vertical sidebar
'\"	# ^Y = starting y location
'\"	# ^v = 1 (for troff;  for nroff this doesn't matter)
.de VS
.if !"\\$2"" .br
.mk ^Y
.ie n 'mc \s12\(br\s0
.el .nr ^v 1u
..
'\"	# VE - end of vertical sidebar
.de VE
.ie n 'mc
.el \{\
.ev 2
.nf
.ti 0
.mk ^t
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
.sp -1
.fi
.ev
.\}
.nr ^v 0
..
'\"	# Special macro to handle page bottom:  finish off current
'\"	# box/sidebar if in box/sidebar mode, then invoked standard
'\"	# page bottom macro.
.de ^B
.ev 2
'ti 0
'nf
.mk ^t
.if \\n(^b \{\
.\"	Draw three-sided box if this is the box's first page,
.\"	draw two sides but no top otherwise.
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.\}
.if \\n(^v \{\
.nr ^x \\n(^tu+1v-\\n(^Yu
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
.\}
.bp
'fi
.ev
.if \\n(^b \{\
.mk ^y
.nr ^b 2
.\}
.if \\n(^v \{\
.mk ^Y
.\}
..
'\"	# DS - begin display
.de DS
.RS
.nf
.sp
..
'\"	# DE - end display
.de DE
.fi
.RE
.sp
..
'\"	# SO - start of list of standard options
.de SO
.SH "STANDARD OPTIONS"
.LP
.nf
.ta 5.5c 11c
.ft B
..
'\"	# SE - end of list of standard options
.de SE
.fi
.ft R
.LP
See the \\fBoptions\\fR manual entry for details on the standard options.
..
'\"	# OP - start of full description for a single option
.de OP
.LP
.nf
.ta 4c
Command-Line Name:	\\fB\\$1\\fR
Database Name:	\\fB\\$2\\fR
Database Class:	\\fB\\$3\\fR
.fi
.IP
..
'\"	# CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
'\"	# CE - end code excerpt
.de CE
.fi
.RE
..
.de UL
\\$1\l'|0\(ul'\\$2
..
.TH fileevent 3tcl 7.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
fileevent \- 在一个通道变得可读或可写的时候执行一个脚本
.SH "总览 SYNOPSIS"
\fBfileevent \fIchannelId \fBreadable \fR?\fIscript\fR?
.sp
\fBfileevent \fIchannelId \fBwritable \fR?\fIscript\fR?
.BE

.SH "描述 DESCRIPTION"
.PP
这个命令被用于建立\fI文件事件处理器\fR。一个文件事件处理器(handler)是在一个通道和一个脚本之间的一个绑定，这样在通道变得可读或可写的时候求这个脚本的值。通常使用文件事件处理器来允许在事件驱动的基础上从另一个进程接收数据，这样接受者可以在等待数据到来的时候继续与用户交互。如果一个应用在一个阻塞(模式下)的通道上调用 \fBgets\fR或 \fBread\fR，而此时没有可获得的数据，在输入数据到来之前，进程将被阻塞，它将不能服务于其他事件，所以对于用户它象是被“冷冻”了。使用 \fBfileevent\fR，进程可以在数据出现(present)的时候被告之，而只在不会导致阻塞的时候调用 \fBgets\fR或 \fBread\fR  。
.PP
给 \fBfileevent\fR的 \fIchannelId\fR   参数参照一个打开的通道，比如从以前的 \fBopen\fR 或 \fBsocket\fR  命令的得到的返回值。如果指定了 \fIscript\fR  参数，则 \fBfileevent\fR  建立一个新的事件处理器: 在通道变得可读或可写(依赖于给 \fBfileevent\fR 的第二个参数)的时候求 \fIscript\fR  的值。在这种情况下 \fBfileevent\fR 返回一个空串。对于一个文件 \fBreadable\fR 和 \fBwritable\fR事件处理器是独立的，可以单独的建立和删除。但是，在一个特定的解释器中在一个特定的时间上对于一个文件最多只能有一个\fBreadable\fR和一个 \fBwritable\fR  处理器。如果调用 \fBfileevent\fR而此时指定的处理器已经在调用的解释器中存在，新的脚本替换旧的那个。  
.PP
如果没有指定 \fIscript\fR  参数，\fBfileevent\fR 为 \fIchannelId\fR返回当前的脚本，如果没有则返回一个空串。如果 指定 \fIscript\fR 参数为一个空串则删除这个事件处理器，如此将不会有脚本被调用。在一个通道被关闭或它的解释器被删除的时候文件的事件处理器也自动的被删除。
.PP
如果在底层的设备上有可获得的未读的数据则把一个通道考虑为可读的。除了要从这个通道读的最近的尝试是不能在输入缓冲中找到一个完整的行的一个 \fBgets\fR  调用的特殊情况之外，如果在一个输入缓冲中有未读的数据也把一个通道考虑未可读的。这个特征允许使用事件从一个在非阻塞模式下的文件中一次读一行。如果在底层的文件或设备上有文件结束或出错的条件出现也把一个通道考虑为可读的。对于 \fIscript\fR 检查这些条件和正确的处理它们是很重要的；例如，如果没有对文件结束的特定检查，可能发生一个无限的循环，这里\fIscript\fR  读不到数据，返回，立即重新调用。
.PP
如果至少数据中有一字节可以写到底层文件或设备中而不阻塞，或者在底层的文件或设备上有错误的条件出现则把一个通道考虑为可写的。    
.PP

事件驱动 I/O 最好为使用 \fBfconfigure\fR  命令配置成非阻塞模式的通道工作。在阻塞模式下，如果你给它的数据比底层文件或数据可接受的多，则 \fBputs\fR 命令将阻塞，而如果你读的数据比已经准备好的多，则\fBgets\fR 或 \fBread\fR 命令将阻塞；在命令阻塞时不处理事件。在非阻塞模式下，\fBputs\fR、\fBread\fR和 \fBgets\fR从不阻塞。参见这些单独命令的文档来得到关于它们如何处理阻塞和非阻塞通道的信息。
.PP
给一个文件事件的脚本在调用\fBfileevent\fR  命令的解释器的全局的层次上执行(在任何 Tcl 过程的上下文之外)。如果在执行脚本期间发生了错误则使用 \fBbgerror\fR 机制来报告错误。额外的，如果一个事件处理器曾经返回错误则删除它；目的是防止缺陷很多的处理器导致无限循环。  

.SH "感谢 CREDITS"
.PP
\fBfileevent\fR  基于由 Mark Diekhans 建立的 \fBaddinput\fR  命令。

.SH "参见 SEE ALSO"
bgerror(n), fconfigure(n), gets(n), puts(n), read(n)

.SH "关键字 KEYWORDS"
asynchronous I/O, blocking, channel, event handler, nonblocking, readable,
script, writable.

.SH "[中文版维护人]"
.B 寒蝉退士
.SH "[中文版最新更新]"
.B 2001/08/13
.SH "《中国 Linux 论坛 man 手册页翻译计划》:"
.BI http://cmpp.linuxforum.net
